/**
 * 跟随手势运动(transform变化)
 * Created by Tenny on 2018/5/8 10:44.
 */

/**
 * 进行对象复制
 */
function extend(t, s) {
  var target = arguments[0] || {}, // 目标对象, 需要复制到的对象
    i = 1, // 当前复制哪个对象
    length = arguments.length,
    deep = false, // 是否需要进行深度复制
    currObj, src, copy, copyIsArray, clone;

  // 判断是否需要进行深度复制
  if(typeof target === 'boolean') {
    deep = taget;
    // 重置目标对象
    target = arguments[i] || {};
    i++;
  }

  if(typeof target !== 'object') {
    target = {};
  }

  // 循环复制每一个对象
  for(; i < length; i++) {
    // 只复制 非空或undefined 对象
    if((currObj = arguments[i]) != null) {
      for(var name in currObj) {
        src = target[name];
        copy = currObj[name];

        if(src === copy) {
          continue
        }

        if(deep && copy && typeof  (isPlainObject(copy) ||
          (copyIsArray = Array.isArray(copy)))) {
          // 允许数组对象的合并去重
          if(copyIsArray) {
            copyIsArray = false;
            clone = Array.isArray(src) ? src : [];
          } else {
            clone = isPlainObject(src) ? src : {};
          }
          target[name] = extend(deep, clone, copy);
        } else if(copy !== undefined && copy !== null) {
          target[name] = copy;
        }
      }
    }
  }
  return target;
}

function noop() {}

let Motion = function(options) {
// 合并配置项
  this.options = extend({
    vertical: false, // 识别的方向, 默认为水平方向
    touchEnd: noop
  }, options);

  this.$elem = typeof options.elem === 'string' ? document.querySelector(options.elem) : options.elem;
  this.current = 0; // 当前的跳过的坐标, 从 0 开始

  // 绑定事件
  this.$elem.addEventListener('touchstart', this._start.bind(this));
  this.$elem.addEventListener('touchmove', this._move.bind(this));
  this.$elem.addEventListener('touchend', this._end.bind(this));
  this.$elem.addEventListener('touchcancel', this._cancel.bind(this));
};

Motion.prototype = {
  _start(evt) {
    this.$elem.style.transition = "none"; // 移除动画效果
    // 记录触摸的坐标(以第一个触摸点为标准)
    this.start = this._getPoint(evt.touches[0]);
  },
  _move(evt) {
    // 获取移动的点
    let movePoint = this._getPoint(evt.touches[0]);
    this._setValue(this.current + movePoint - this.start);
  },
  _end(evt) {
    let point = this._getPoint(evt.changedTouches[0]);
    let oldCurr = this.current;
    this.current = this.current + point - this.start;
    this.options.touchEnd(evt, {
      end: point,
      start: this.start,
      current: oldCurr
    });
  },
  _cancel(evt) {
    this._setValue(this.current);
  },
  _setValue(value) {
    this.$elem.style.transform = this.options.property + "(" + value + "px)";
  },
  /**
   * 获取当前坐标点
   * @param touch       触摸 Touch 对象
   * @returns {number}
   * @private
   */
  _getPoint(touch) {
    // 记录触摸的坐标(以第一个触摸点为标准)
    let startX = touch.pageX;
    let startY = touch.pageY;
    return this.options.vertical === true ? startY : startX;
  },

  /**
   * 移动到指定位置
   */
  to(value) {
    this.$elem.style.transition = "all .2s linear"; // 添加动画效果
    this.current = value;
    this._setValue(value);
  }
};

export default Motion;
